#include "WidgetAnimation.h"
#include "WidgetAnimationTrigger.h"
#include "Time/Time.h"

//simple lerp float value
//auto start when first time used
class CSimpleAnimatedFloatValueGetter : public TWidgetAttributeValueGetterBase
{
public:
    //widget attribute interface
    virtual void GetValuePointer(void* OutValue) override
    {
        switch(State)
        {
            case EState::Uninitialized:
                State=EState::Playing;
                StartTime=std::chrono::steady_clock::now();
                *reinterpret_cast<float*>(OutValue) = InitialValue.Get();
                return;
            case EState::Playing:
                {
                    float _Duration= Duration.Get();
                    float ElapsedTime = WH::GetSecondsFrom(StartTime);
                    float Alpha = ElapsedTime / _Duration;
                    if(Alpha>=1.0f)
                    {
                        State=EState::Stopped;
                        *reinterpret_cast<float*>(OutValue) = TargetValue.Get();
                        return;
                    }
                    float _InitialValue = InitialValue.Get();
                    float _TargetValue = TargetValue.Get();
                    *reinterpret_cast<float*>(OutValue)= _InitialValue + (_TargetValue - _InitialValue) * Alpha;
                }
                return;
            case EState::Stopped:
                *reinterpret_cast<float*>(OutValue) = TargetValue.Get();
                return;
        }
    }

public:
    CSimpleAnimatedFloatValueGetter(TWidgetAttribute<float> InInitialValue, TWidgetAttribute<float> InTargetValue, TWidgetAttribute<float> InDuration)
        :InitialValue(InInitialValue)
        ,TargetValue(InTargetValue)
        ,Duration(InDuration)
    {
    }

    TWidgetAttribute<float> InitialValue;
    TWidgetAttribute<float> TargetValue;
    TWidgetAttribute<float> Duration;

    enum class EState
    {
        Uninitialized,
        Playing,
        Stopped
    };

    EState State = EState::Uninitialized;
    std::chrono::steady_clock::time_point StartTime ; // time when the animation starts

public:
 
};

class CBinkColorValueGetter : public TWidgetAttributeValueGetterBase
{
public:
    CBinkColorValueGetter(TSharedObjectPtr<RWidgetAnimationTrigger> InCondition, TWidgetAttribute<SColor> InNormalColor, TWidgetAttribute<SColor> InAnotherColor, TWidgetAttribute<float> InOneColorDuration)
        :Condition(InCondition)
        ,NormalColor(InNormalColor)
        ,AnotherColor(InAnotherColor)
        ,OneColorDuration(InOneColorDuration)
    {
    }

    //widget attribute interface
    virtual void GetValuePointer(void* OutValue) override
    {
        bool bIsActive = Condition->IsActive();
        if(!bIsActive)
        {
            *reinterpret_cast<SColor*>(OutValue) = NormalColor.Get();
            FormerIsActive=false;
            return;
        }

        if(!FormerIsActive)
        {
            //first time to blink
            StartTime=std::chrono::steady_clock::now();
            FormerIsActive=true;
            *reinterpret_cast<SColor*>(OutValue) = AnotherColor.Get();
            return;
        }

        float ElapsedTime = WH::GetSecondsFrom(StartTime);
        float _OneColorDuration = OneColorDuration.Get();

        bool bIsNormalColor =(int)(ElapsedTime / _OneColorDuration) % 2;
        if(bIsNormalColor)
        {
            *reinterpret_cast<SColor*>(OutValue) = NormalColor.Get();
        }
        else
        {
            *reinterpret_cast<SColor*>(OutValue) = AnotherColor.Get();
        }

    }

protected:
    TSharedObjectPtr<RWidgetAnimationTrigger> Condition;
    TWidgetAttribute<SColor> NormalColor;
    TWidgetAttribute<SColor> AnotherColor;
    TWidgetAttribute<float> OneColorDuration;

    bool FormerIsActive = false;
    std::chrono::steady_clock::time_point StartTime; // time when the animation starts

};

TWidgetAttribute<float> SAnimatedAttributeCreator::CreateFloatAttribute(
    TWidgetAttribute<float> InitialValue,
    TWidgetAttribute<float> TargetValue, 
    TWidgetAttribute<float> Duration )
{
    return TWidgetAttribute<float>(
        std::make_shared<CSimpleAnimatedFloatValueGetter>(InitialValue, TargetValue, Duration)
    );
}

TWidgetAttribute<SColor> SAnimatedAttributeCreator::CreateColorBlinkAttribute(
    TSharedObjectPtr<RWidgetAnimationTrigger> Condition, 
    TWidgetAttribute<SColor> NormalColor,
    TWidgetAttribute<SColor> AnotherColor, 
    TWidgetAttribute<float> OneColorDuration)
{
    return TWidgetAttribute<SColor>(
        std::make_shared<CBinkColorValueGetter>(Condition, NormalColor, AnotherColor, OneColorDuration)
    );
}
